home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet Info 1994 March
/
Internet Info CD-ROM (Walnut Creek) (March 1994).iso
/
networking
/
ip
/
ka9q
/
MNetsrc.hqx
/
Mac TCP_IP Source v.33
/
ax_mbx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-03-03
|
19KB
|
878 lines
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include "global.h"
#ifdef MAC
#include "config.h"
#include <types.h>
#endif
#include "mbuf.h"
#include "ax25.h"
#include "timer.h"
#include "iface.h"
#include "lapb.h"
#include "netrom.h"
#include "nr4.h"
#include "ax_mbx.h"
#include "cmdparse.h"
/*
#define MBDEBUG
*/
struct mbx *mbox[NUMMBX] ;
int ax25mbox ;
#ifdef CALLBK
static char mbbanner[] =
"[NET-$]\rWelcome to the %s TCP/IP Mailbox\r(C)hat, (I)nquire, (S)end, (B)ye >\r" ;
static char mbmenu[] = "(C)hat, (I)nquire, (S)end, (B)ye >\r" ;
#else
static char mbbanner[] =
"[NET-$]\rWelcome to the %s TCP/IP Mailbox\r(C)hat, (S)end, (B)ye >\r" ;
static char mbmenu[] = "(C)hat, (S)end, (B)ye >\r" ;
#endif
dombox(argc, argv)
int argc ;
char *argv[] ;
{
if (argc < 2) {
domboxdisplay() ;
return 0 ;
}
if (argv[1][0] == 'y' || (strcmp(argv[1],"on") == 0))
ax25mbox = 1 ;
else if (argv[1][0] == 'n' || (strcmp(argv[1],"off") == 0))
ax25mbox = 0 ;
else if (argv[1][0] == '?')
printf("ax25 mailbox is %s\n", ax25mbox ? "on" : "off") ;
else
printf("usage: mbox [y|n|?]\n") ;
return 0 ;
}
static domboxdisplay()
{
int i ;
struct mbx *m ;
static char *states[] = {"NONE","CMD","SUBJ","DATA"} ;
static char *mbtype[] = {"NONE","AX25 ","NET/ROM"} ;
printf(" User State Type &cb\n") ;
for (i = 0 ; i < NUMMBX ; i++)
if ((m = mbox[i]) != NULLMBX)
printf("%-10s %-4s %-7s ", m->name, states[m->state],
mbtype[m->type]);
if (m->type == MBX_AX25)
printf("%04x\n",m->cb.ax25_cb);
else
printf("%04x\n",m->cb.nr4_cb);
}
static struct mbx *
newmbx()
{
int i ;
struct mbx *m ;
for (i = 0 ; i < NUMMBX ; i++)
if (mbox[i] == NULLMBX) {
if ((m = mbox[i] = (struct mbx *)calloc(1,sizeof(struct mbx)))
== NULLMBX)
return NULLMBX ;
m->mbnum = i ;
return m ;
}
/* If we get here, there are no free mailbox sessions */
return NULLMBX ;
}
/* Incoming mailbox session via ax.25 */
void
mbx_incom(axp,cnt)
register struct ax25_cb *axp ;
int16 cnt ;
{
struct mbx *m ;
struct mbuf *bp, *recv_ax25() ;
char *cp ;
extern char hostname[] ;
void mbx_rx(), mbx_state() ;
extern char *index() ;
if ((m = newmbx()) == NULLMBX) {
disc_ax25(axp) ; /* no memory! */
return ;
}
m->state = MBX_CMD ; /* start in command state */
m->type = MBX_AX25 ; /* this is an ax.25 mailbox session */
m->cb.ax25_cb = axp ;
pax25(m->name,&axp->addr.dest) ;
cp = index(m->name,'-') ;
if (cp != NULLCHAR) /* get rid of SSID */
*cp = '\0' ;
m->lp = m->line ; /* point line pointer at buffer */
axp->r_upcall = mbx_rx ;
axp->s_upcall = mbx_state ;
axp->user = (char *)m ;
/* The following is necessary because we didn't know we had a */
/* "real" ax25 connection until a data packet came in. We */
/* can't be spitting banners out at every station who connects, */
/* since they might be a net/rom or IP station. Sorry. */
bp = recv_ax25(axp,cnt) ; /* get the initial input */
free_p(bp) ; /* and throw it away to avoid confusion */
/* Now say hi */
if ((bp = alloc_mbuf(strlen(hostname) + strlen(mbbanner) + 2)) == NULLBUF) {
disc_ax25(axp) ; /* mbx_state will fix stuff up */
return ;
}
*bp->data = PID_FIRST | PID_LAST | PID_NO_L3 ; /* pid */
(void)sprintf(bp->data+1,mbbanner,hostname) ;
bp->cnt = strlen(bp->data+1) + 1 ;
send_ax25(axp,bp) ; /* send greeting message and menu */
}
/* receive upcall for ax.25 */
/* mbx_rx collects lines, and calls mbx_line when they are complete. */
/* If the lines get too long, it arbitrarily breaks them. */
void mbx_rx(axp,cnt)
struct ax25_cb *axp ;
int16 cnt ;
{
struct mbuf *bp, *recv_ax25() ;
struct mbx *m ;
char c ;
int mbx_line() ;
m = (struct mbx *)axp->user ;
if ((bp = recv_ax25(axp,cnt)) == NULLBUF)
return ;
while (pullup(&bp,&c,1) == 1) {
if (c == '\r') {
*m->lp = '\0' ; /* null terminate */
if (mbx_line(m) == -1) { /* call the line processor */
free_p(bp) ; /* toss the rest */
break ; /* get out - we're obsolete */
}
m->lp = m->line ; /* reset the pointer */
}
else if ((m->lp - m->line) == (MBXLINE - 1)) {
*m->lp++ = c ;
*m->lp = '\0' ;
if (mbx_line(m) == -1) {
free_p(bp) ;
break ;
}
m->lp = m->line ;
}
else
*m->lp++ = c ;
}
}
/* state upcall for ax.25 */
void mbx_state(axp,old,new)
struct ax25_cb *axp ;
int old, new ;
{
struct mbx *m ;
void free_mbx() ;
m = (struct mbx *)axp->user ;
/* dummy for now ... */
if (new == DISCONNECTED) {
axp->user = NULLCHAR ;
free_mbx(m) ;
}
}
/* Incoming mailbox session via net/rom */
void
mbx_nr4incom(cb)
register struct nr4cb *cb ;
{
struct mbx *m ;
struct mbuf *bp ;
char *cp ;
extern char hostname[] ;
void mbx_nr4rx(), mbx_nr4state() ;
extern char *index() ;
if ((m = newmbx()) == NULLMBX) {
disc_nr4(cb) ; /* no memory! */
return ;
}
m->state = MBX_CMD ; /* start in command state */
m->type = MBX_NETROM ; /* mailbox session type is net/rom */
m->cb.nr4_cb = cb ;
pax25(m->name,&cb->user) ;
cp = index(m->name,'-') ;
if (cp != NULLCHAR) /* get rid of SSID */
*cp = '\0' ;
m->lp = m->line ; /* point line pointer at buffer */
cb->r_upcall = mbx_nr4rx ;
cb->s_upcall = mbx_nr4state ;
cb->puser = (char *)m ;
/* Say hi */
if ((bp = alloc_mbuf(strlen(hostname) + strlen(mbbanner) + 1)) == NULLBUF) {
disc_nr4(cb) ; /* mbx_nr4state will fix stuff up */
return ;
}
(void)sprintf(bp->data,mbbanner,hostname) ;
bp->cnt = strlen(bp->data) ;
send_nr4(cb,bp) ; /* send greeting message and menu */
}
/* receive upcall for net/rom */
/* mbx_nr4rx collects lines, and calls mbx_line when they are complete. */
/* If the lines get too long, it arbitrarily breaks them. */
void mbx_nr4rx(cb,cnt)
struct nr4cb *cb ;
int16 cnt ;
{
struct mbuf *bp ;
struct mbx *m ;
char c ;
int mbx_line() ;
m = (struct mbx *)cb->puser ;
if ((bp = recv_nr4(cb,cnt)) == NULLBUF)
return ;
while (pullup(&bp,&c,1) == 1) {
if (c == '\r') {
*m->lp = '\0' ; /* null terminate */
if (mbx_line(m) == -1) { /* call the line processor */
free_p(bp) ; /* toss the rest */
break ; /* get out - we're obsolete */
}
m->lp = m->line ; /* reset the pointer */
}
else if ((m->lp - m->line) == (MBXLINE - 1)) {
*m->lp++ = c ;
*m->lp = '\0' ;
if (mbx_line(m) == -1) {
free_p(bp) ;
break ;
}
m->lp = m->line ;
}
else
*m->lp++ = c ;
}
}
/* state upcall for net/rom */
void mbx_nr4state(cb,old,new)
struct nr4cb *cb ;
int old, new ;
{
struct mbx *m ;
void free_mbx() ;
m = (struct mbx *)cb->puser ;
if (new == NR4STDISC) {
cb->puser = NULLCHAR ;
free_mbx(m) ;
}
}
static void
free_mbx(m)
struct mbx *m ;
{
if (m->to != NULLCHAR)
free(m->to) ;
if (m->tofrom != NULLCHAR)
free(m->tofrom) ;
if (m->tomsgid != NULLCHAR)
free(m->tomsgid) ;
if (m->tfile != NULLFILE)
fclose(m->tfile) ;
mbox[m->mbnum] = NULLMBX ;
free(m) ;
}
static
mbx_line(m)
struct mbx *m ;
{
void ax_session(), nr4_session() ;
char *host ;
extern char hostname[] ;
#ifdef MAC
char fullfrom[256] ;
#else
char fullfrom[50] ;
#endif
#ifdef CALLBK
extern char *index();
char *cp;
#endif
if (m->state == MBX_CMD) {
switch (tolower(m->line[0])) {
case 'b': /* bye - bye */
switch (m->type) {
case MBX_AX25:
disc_ax25(m->cb.ax25_cb) ;
break ;
case MBX_NETROM:
disc_nr4(m->cb.nr4_cb) ;
break ;
}
return -1 ; /* tell line processor to quit */
break ;
case 'c': /* chat */
switch (m->type) {
case MBX_AX25:
m->cb.ax25_cb->user = NULLCHAR ;
ax_session(m->cb.ax25_cb,0) ; /* make it a chat session */
break ;
case MBX_NETROM:
m->cb.nr4_cb->puser = NULLCHAR ;
nr4_session(m->cb.nr4_cb) ;
break ;
}
free_mbx(m) ;
return -1 ;
break ;
#ifdef CALLBK
case 'i': /* inquire */
if ((cp = rindex(m->line,' ')) != NULLCHAR) {
cp++;
mac_callbka(m,cp);
mbx_msg(m,mbmenu);
break;
}
else {
mbx_msg(m,
"I command syntax error - format is:\r") ;
mbx_msg(m,
" Inquire [callsign]\r") ;
break;
}
#endif
case 's': {
int badsubj = 0 ;
/* Get S-command type (B,P,T, etc.) */
if (m->line[1] == '\0')
m->stype = ' ' ;
else
m->stype = toupper(m->line[1]) ;
if (mbx_to(m) == -1) {
if (m->mblforw)
mbx_msg(m,"NO\r") ;
else {
mbx_msg(m,
"S command syntax error - format is:\r") ;
mbx_msg(m,
" S name [@ host] [< from_addr] [$bulletin_id]\r") ;
}
badsubj++ ;
}
else if (validate_address(m->to) == 0) {
if (m->mblforw)
mbx_msg(m, "NO\r") ;
else
mbx_msg(m, "Bad user or host name\r") ;
free(m->to) ;
m->to = NULLCHAR ;
if (m->tofrom) {
free(m->tofrom) ;
m->tofrom = NULLCHAR ;
}
if (m->tomsgid) {
free(m->tomsgid) ;
m->tomsgid = NULLCHAR ;
}
badsubj++ ;
}
if (badsubj)
mbx_msg(m, m->mblforw ? ">\r" : mbmenu) ;
else {
m->state = MBX_SUBJ ;
mbx_msg(m, m->mblforw ? "OK\r" : "Subject:\r") ;
}
break ;
}
case '[': /* This is an MBL BBS - say "OK", not "Subject:" */
if (m->line[strlen(m->line) - 1] == ']') {
m->mblforw = 1 ;
mbx_msg(m,">\r") ;
}
break ;
case 'f':
if (m->line[1] == '>' && m->mblforw) {
mbx_msg(m,">\r") ;
break ;
}
/* Otherwise drop through to "huh?" */
default:
mbx_msg(m,"Huh?\r") ;
mbx_msg(m, m->mblforw ? ">\r" : mbmenu) ;
}
return 0 ;
}
else if (m->state == MBX_SUBJ) {
if (mbx_data(m) == -1) {
mbx_msg(m,"Can't create temp file for mail\r") ;
mbx_msg(m, m->mblforw ? ">\r" : mbmenu) ;
free(m->to) ;
m->to = NULLCHAR ;
if (m->tofrom) {
free(m->tofrom) ;
m->tofrom = NULLCHAR ;
}
if (m->tomsgid) {
free(m->tomsgid) ;
m->tomsgid = NULLCHAR ;
}
m->state = MBX_CMD ;
return 0 ;
}
m->state = MBX_DATA ;
if (m->mblforw == 0)
mbx_msg(m,
"Enter message. Terminate with /EX or ^Z in first column:\r") ;
return 0 ;
}
else if (m->state == MBX_DATA) {
if (m->line[0] == 0x1a ||
strcmp(m->line, "/ex") == 0 ||
strcmp(m->line, "/EX") == 0) {
if ((host = index(m->to,'@')) == NULLCHAR)
host = hostname ; /* use our hostname */
else
host++ ; /* use the host part of address */
/* make up full from name for work file */
(void)sprintf(fullfrom,"%s@%s",m->name,hostname) ;
fseek(m->tfile,0L,0) ; /* reset to beginning */
if (queuejob((void *)0,m->tfile,host,m->to,fullfrom) != 0)
mbx_msg(m,
"Couldn't queue message for delivery\r") ;
free(m->to) ;
m->to = NULLCHAR ;
if (m->tofrom) {
free(m->tofrom) ;
m->tofrom = NULLCHAR ;
}
if (m->tomsgid) {
free(m->tomsgid) ;
m->tomsgid = NULLCHAR ;
}
fclose(m->tfile) ;
m->tfile = NULLFILE ;
m->state = MBX_CMD ;
mbx_msg(m, m->mblforw ? ">\r" : mbmenu) ;
return 0 ;
}
/* not done yet! */
fprintf(m->tfile,"%s\n",m->line) ;
return 0 ;
}
}
#ifndef CALLBK
static
#endif
mbx_msg(m,msg)
struct mbx *m ;
char msg[] ;
{
int len ;
struct mbuf *bp ;
struct ax25_cb *axp ;
struct nr4cb *cb ;
len = strlen(msg) ;
switch (m->type) {
case MBX_AX25:
axp = m->cb.ax25_cb ;
if ((bp = alloc_mbuf(len+1)) == NULLBUF) {
disc_ax25(axp) ;
return -1 ;
}
bp->cnt = len + 1 ;
*bp->data = PID_FIRST | PID_LAST | PID_NO_L3 ;
memcpy(bp->data+1, msg, len) ;
send_ax25(axp,bp) ;
break ;
case MBX_NETROM:
cb = m->cb.nr4_cb ;
if ((bp = alloc_mbuf(len)) == NULLBUF) {
disc_nr4(cb) ;
return -1 ;
}
bp->cnt = len ;
memcpy(bp->data, msg, len) ;
send_nr4(cb, bp) ;
break ;
}
return 0 ;
}
/* States for send line parser state machine */
#define SKIP_CMD 1
#define LOOK_FOR_USER 2
#define IN_USER 3
#define AFTER_USER 4
#define LOOK_FOR_HOST 5
#define IN_HOST 6
#define AFTER_HOST 7
#define LOOK_FOR_FROM 8
#define IN_FROM 9
#define AFTER_FROM 10
#define LOOK_FOR_MSGID 11
#define IN_MSGID 12
#define FINAL_STATE 13
#define ERROR_STATE 14
/* Prepare the addressee. If the address is bad, return -1, otherwise
* return 0
*/
static
mbx_to(m)
struct mbx *m ;
{
register char *cp, *cp1 ;
int state ;
char *user, *host, *from, *msgid ;
int userlen = 0, hostlen = 0, fromlen = 0, msgidlen = 0 ;
cp = m->line ;
for (state = SKIP_CMD ; state < FINAL_STATE ; cp++) {
#ifdef MBDEBUG
printf("State is %d, char is %c\n", state, *cp) ;
#endif
switch (state) {
case SKIP_CMD:
if (*cp == '\0')
state = ERROR_STATE ; /* no user */
else if (isspace(*cp))
state = LOOK_FOR_USER ;
break ;
case LOOK_FOR_USER:
if (*cp == '\0' || *cp == '@' || *cp == '<' || *cp == '$')
state = ERROR_STATE ; /* no user */
else if (!isspace(*cp)) { /* found start of user */
user = cp ; /* point at start */
userlen++ ; /* start counting */
state = IN_USER ;
}
break ;
case IN_USER:
switch (*cp) {
case '\0': /* found username only */
state = FINAL_STATE ;
break ;
case '@':
state = LOOK_FOR_HOST ; /* hostname should follow */
break ;
case '<':
state = LOOK_FOR_FROM ; /* from name should follow */
break ;
case '$':
state = LOOK_FOR_MSGID ; /* message id should follow */
break ;
default:
if (isspace(*cp))
state = AFTER_USER ; /* white space */
else
userlen++ ; /* part of username */
}
break ;
case AFTER_USER:
switch (*cp) {
case '\0':
state = FINAL_STATE ; /* found username only */
break ;
case '@':
state = LOOK_FOR_HOST ; /* hostname follows */
break ;
case '<':
state = LOOK_FOR_FROM ; /* fromname follows */
break ;
case '$':
state = LOOK_FOR_MSGID ; /* message id follows */
break ;
default:
if (!isspace(*cp))
state = ERROR_STATE ;
}
break ;
case LOOK_FOR_HOST:
switch (*cp) {
case '\0': /* user@? */
case '@': /* user@@ */
case '<': /* user@< */
case '$': /* user@$ */
state = ERROR_STATE ;
break ;
default:
if (!isspace(*cp)) {
host = cp ;
hostlen++ ;
state = IN_HOST ;
}
}
break ;
case IN_HOST:
switch (*cp) {
case '\0':
state = FINAL_STATE ; /* found user@host */
break ;
case '@':
state = ERROR_STATE ; /* user@host@? */
break ;
case '<':
state = LOOK_FOR_FROM ; /* fromname follows */
break ;
case '$':
state = LOOK_FOR_MSGID ; /* message id follows */
break ;
default:
if (isspace(*cp))
state = AFTER_HOST ;
else
hostlen++ ;
}
break ;
case AFTER_HOST:
switch (*cp) {
case '\0':
state = FINAL_STATE ; /* user@host */
break ;
case '@':
state = ERROR_STATE ; /* user@host @ */
break ;
case '<':
state = LOOK_FOR_FROM ; /* user@host < */
break ;
case '$':
state = LOOK_FOR_MSGID ; /* user@host $ */
break ;
default:
if (!isspace(*cp))
state = ERROR_STATE ; /* user@host foo */
}
break ;
case LOOK_FOR_FROM:
switch (*cp) {
case '\0': /* user@host <? */
case '@': /* user@host <@ */
case '<': /* user@host << */
case '$': /* user@host <$ */
state = ERROR_STATE ;
break ;
default:
if (!isspace(*cp)) {
from = cp ;
fromlen++ ;
state = IN_FROM ;
}
}
break ;
case IN_FROM:
switch (*cp) {
case '\0':
state = FINAL_STATE ; /* user@host <foo */
break ;
case '<':
state = ERROR_STATE ; /* user@host <foo< */
break ;
case '$':
state = LOOK_FOR_MSGID ; /* message id follows */
break ;
default:
if (isspace(*cp))
state = AFTER_FROM ;
else
fromlen++ ;
}
break ;
case AFTER_FROM:
switch (*cp) {
case '\0':
state = FINAL_STATE ; /* user@host <foo */
break ;
case '@': /* user@host <foo @ */
case '<': /* user@host <foo < */
state = ERROR_STATE ;
break ;
case '$':
state = LOOK_FOR_MSGID ; /* user@host <foo $ */
break ;
default:
if (!isspace(*cp))
state = ERROR_STATE ; /* user@host foo */
}
break ;
case LOOK_FOR_MSGID:
if (*cp == '\0')
state = ERROR_STATE ; /* msgid = $? */
else if (isspace(*cp))
state = ERROR_STATE ; /* user@host <foo $ bar */
else {
msgid = cp ;
msgidlen++ ;
state = IN_MSGID ;
}
break ;
case IN_MSGID:
if (*cp == '\0')
state = FINAL_STATE ;
else if (isspace(*cp))
state = FINAL_STATE ;
else
msgidlen++ ;
break ;
default:
/* what are we doing in this state? */
state = ERROR_STATE ;
}
}
if (state == ERROR_STATE)
return -1 ; /* syntax error */
if ((m->to = malloc(userlen + hostlen + 2)) == NULLCHAR)
return -1 ; /* no room for to address */
strncpy(m->to, user, userlen) ;
m->to[userlen] = '\0' ;
if (hostlen) {
m->to[userlen] = '@' ;
strncpy(m->to + userlen + 1, host, hostlen) ;
m->to[userlen + hostlen + 1] = '\0' ;
}
if (fromlen) {
if ((m->tofrom = malloc(fromlen + 1)) == NULLCHAR) {
free(m->to) ;
m->to = NULLCHAR ;
return -1 ;
}
strncpy(m->tofrom, from, fromlen) ;
m->tofrom[fromlen] = '\0' ;
}
if (msgidlen) {
if ((m->tomsgid = malloc(msgidlen + 1)) == NULLCHAR) {
free(m->to) ;
m->to = NULLCHAR ;
if (fromlen) {
free(m->tofrom) ;
m->tofrom = NULLCHAR ;
}
return -1 ;
}
strncpy(m->tomsgid, msgid, msgidlen) ;
m->tomsgid[msgidlen] = '\0' ;
}
return 0 ;
}
/* This opens the data file and writes the mail header into it.
* Returns 0 if OK, and -1 if not.
*/
static
mbx_data(m)
struct mbx *m ;
{
time_t t;
char *ptime() ;
extern char hostname[] ;
extern FILE *tmpfile();
extern long get_msgid() ;
if ((m->tfile = tmpfile()) == NULLFILE)
return -1 ;
time(&t) ;
fprintf(m->tfile,"Date: %s",ptime(&t)) ;
if (m->tomsgid)
fprintf(m->tfile, "Message-Id: <%s@%s>\n", m->tomsgid, hostname) ;
else
fprintf(m->tfile,"Message-Id: <%ld@%s>\n",get_msgid(),hostname) ;
fprintf(m->tfile,"From: %s%%%s.bbs@%s\n",
m->tofrom ? m->tofrom : m->name, m->name, hostname) ;
fprintf(m->tfile,"To: %s\n",m->to) ;
fprintf(m->tfile,"Subject: %s\n",m->line) ;
if (m->stype != ' ')
fprintf(m->tfile,"X-BBS-Msg-Type: %c\n", m->stype) ;
fprintf(m->tfile,"\n") ;
return 0 ;
}